有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java通过数字id获取枚举的最佳方法

我需要创建一个大约有300个值的枚举,并且能够通过id(int)获取其值。我目前有:

public enum Country {
    DE(1), US(2), UK(3);

    private int id;
    private static Map<Integer, Country> idToCountry = new HashMap<>();
    static {
        for (Country c : Country.values()) {
            idToCountry.put(c.id, c);
        }
    }

    Country(int id) {
        this.id = id;
    }

    public static Country getById(int id) {
        return idToCountry.get(id);
    }
}

这个枚举将被大量使用,所以我想知道这是否是性能方面最好的解决方案

我一遍又一遍地读http://docs.oracle.com/javase/1.5.0/docs/guide/language/enums.html,但找不到描述时间的部分

static {

}

块被调用,如果保证只调用一次。是吗


共 (4) 个答案

  1. # 1 楼答案

    如果第一个国家id为0,且id增加了1,则可以使用下一种方法:

    1. 在数组中缓存枚举值Enum.values()返回元素的顺序与它们在enum中声明的顺序相同。但它应该被缓存,因为它每次被调用时都会创建新的数组
    2. 按id从缓存的数组中获取值,id将作为数组索引

    请参见下面的代码:

    enum Country {
        A, B, C, D, E;
        private static final Country[] values = Country.values();
    
        public static Country getById(int id) {
            return values[id];
        }
    }
    

    更新:要获取国家id,应使用ordinal()方法。为了更清楚地获取id代码,可以在枚举中添加下一种方法:

    public int getId() {
        return ordinal();
    }
    
  2. # 2 楼答案

    首先,创建地图不需要静态块。您只需将代码添加到构造函数中,每个组件都会将自己添加到映射中。Enum始终是一个sigleton,因此您的构造函数保证只被调用一次(每个Enum值),而且您甚至不需要ID,因为Enum的方法public final int ordinal()在Enum中返回其从零开始的序列号。在你的例子中,序数是0代表DE,1代表US,2代表UK

    下面是一个例子:

    public enum Country {
    DE, US, UK;
    
    private static Map<Integer, Country> idToCountry = new HashMap<>();
    
        Country() {
           idToCountry.put(this.ordinal(), this);
        }
    
        public static Country getById(int id) {
            return idToCountry.get(id);
        }
    }
    
  3. # 3 楼答案

    静态初始值设定项块被调用一次when the class is initialized。它不能保证只被调用一次,但除非你在用类装入器做一些异国情调的事情

    因此,从性能角度来看,您的方法可能是很好的。我建议的唯一改变是将字段final


    表示映射的另一种方法是将元素存储在数组(或列表)中:

    Country[] countries = new Countries[maxId + 1];
    for (Country country : Country.values()) {
      countries[country.id] = country;
    }
    

    然后可以通过元素索引查找它们:

    System.out.println(countries[1]);  // DE.
    

    这避免了为了调用idToCountry.get(Integer)而必须将id框起来的性能损失

    当然,这需要您拥有非阴性ID(理想情况下,ID应该是合理连续的,以避免在国家之间存储大量null

  4. # 4 楼答案

    你也可以试试这个。这很简单

    enum Country {
      DE(1), US(2), UK(3);
    
      public int id;
    
      Country(int id) {
      this.id = id;
    }
    
     public static Country getCountry(int id) {
        Country[] c = new Country[Country.values().length];
        c = Country.values();
        return c[id];
      }
    }
    

    非常感谢